//面试题 08.01. 三步问题
/*三步问题。有个小孩正在上楼梯，楼梯有 n 阶台阶，小孩一次可以上 1 阶、2 阶或 3 阶。实现一种方法，计算小孩有多少种上楼梯的方式。结果可能很大，你需要对结果模 1000000007。
n 范围在[1, 1000000]之间
*/
class Solution {
public:
    int waysToStep(int n) {
        if (n == 1)
            return 1;
        if (n == 2)
            return 2;
        if (n == 3)
            return 4;
        vector<int> nums(n + 1);
        nums[1] = 1;
        nums[2] = 2;
        nums[3] = 4;
        int mod = 1e9 + 7;
        for (int i = 4; i <= n; i++) {
            nums[i] = ((nums[i - 1] + nums[i - 2]) % mod + nums[i - 3]) % mod;
        }
        return nums[n];
    }
};
//使用最小花费爬楼梯
/*数组的每个下标作为一个阶梯，第 i 个阶梯对应着一个非负数的体力花费值 cost[i]（下标从 0 开始）。
每当爬上一个阶梯都要花费对应的体力值，一旦支付了相应的体力值，就可以选择向上爬一个阶梯或者爬两个阶梯。
请找出达到楼层顶部的最低花费。在开始时，你可以选择从下标为 0 或 1 的元素作为初始阶梯。
*/
class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        if (cost.size() == 2)
            return min(cost[0], cost[1]);
        vector<int> dp(cost.size() + 1);
        dp[0] = dp[1] = 0;
        for (int i = 2; i <= cost.size(); i++) {
            dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        }
        return dp[cost.size()];
    }
};


//解码方法
/*一条包含字母 A-Z 的消息通过以下映射进行了 编码 ：

"1" -> 'A'

"2" -> 'B'

...

"25" -> 'Y'

"26" -> 'Z'

然而，在 解码 已编码的消息时，你意识到有许多不同的方式来解码，因为有些编码被包含在其它编码当中（"2" 和 "5" 与 "25"）。

例如，"11106" 可以映射为：

"AAJF" ，将消息分组为 (1, 1, 10, 6)
"KJF" ，将消息分组为 (11, 10, 6)
消息不能分组为  (1, 11, 06) ，因为 "06" 不是一个合法编码（只有 "6" 是合法的）。
注意，可能存在无法解码的字符串。

给你一个只含数字的 非空 字符串 s ，请计算并返回 解码 方法的 总数 。如果没有合法的方式解码整个字符串，返回 0。

题目数据保证答案肯定是一个 32 位 的整数。
1 <= s.length <= 100
s 只包含数字，并且可能包含前导零。
*/
class Solution {
public:
    int numDecodings(string s) {
        int size = s.size();
        vector<int> dp(size);
        if (s[0] == '0')
            return 0;
        dp[0] = 1;
        if (size == 1)
            return dp[0];
        int num1 = s[1] - '0';
        if (num1 >= 1 && num1 <= 9)
            dp[1] += dp[0];
        int num2 = (s[0] - '0') * 10 + s[1] - '0';
        if (num2 >= 10 && num2 <= 26)
            dp[1] += 1;
        for (int i = 2; i < size; i++) {
            int num1 = s[i] - '0';
            if (num1 >= 1 && num1 <= 9)
                dp[i] += dp[i - 1];
            int num2 = (s[i - 1] - '0') * 10 + s[i] - '0';
            if (num2 >= 10 && num2 <= 26)
                dp[i] += dp[i - 2];
        }
        return dp[size - 1];
    }
};